package com.uduemc.biso.node.web.service.impl;

import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.github.pagehelper.PageInfo;
import com.uduemc.biso.core.extities.center.Site;
import com.uduemc.biso.core.extities.center.SysLanguage;
import com.uduemc.biso.node.core.common.dto.FeignPageUtil;
import com.uduemc.biso.node.core.common.entities.HostInfos;
import com.uduemc.biso.node.core.common.entities.SRHtml;
import com.uduemc.biso.node.core.common.entities.SitePage;
import com.uduemc.biso.node.core.common.entities.srhtml.SRBody;
import com.uduemc.biso.node.core.common.entities.srhtml.SRHead;
import com.uduemc.biso.node.core.common.utils.SRHtmlUtil;
import com.uduemc.biso.node.core.entities.HConfig;
import com.uduemc.biso.node.core.entities.SCategories;
import com.uduemc.biso.node.core.entities.SConfig;
import com.uduemc.biso.node.core.entities.SPage;
import com.uduemc.biso.node.core.entities.SProduct;
import com.uduemc.biso.node.core.entities.SSystem;
import com.uduemc.biso.node.core.entities.SSystemItemCustomLink;
import com.uduemc.biso.node.core.entities.custom.Article;
import com.uduemc.biso.node.core.entities.custom.ProductDataTableForList;
import com.uduemc.biso.node.core.utils.SiteUrlUtil;
import com.uduemc.biso.node.web.component.RequestHolder;
import com.uduemc.biso.node.web.component.SiteUrlComponent;
import com.uduemc.biso.node.web.entities.AccessPage;
import com.uduemc.biso.node.web.entities.AccessSite;
import com.uduemc.biso.node.web.exception.NotFound404Exception;
import com.uduemc.biso.node.web.service.SRBodyService;
import com.uduemc.biso.node.web.service.SRHeadService;
import com.uduemc.biso.node.web.service.SitemapService;
import com.uduemc.biso.node.web.service.byfeign.ArticleService;
import com.uduemc.biso.node.web.service.byfeign.HostService;
import com.uduemc.biso.node.web.service.byfeign.LanguageService;
import com.uduemc.biso.node.web.service.byfeign.PageService;
import com.uduemc.biso.node.web.service.byfeign.ProductService;
import com.uduemc.biso.node.web.service.byfeign.SiteConfigService;
import com.uduemc.biso.node.web.service.byfeign.SiteService;
import com.uduemc.biso.node.web.service.byfeign.SystemService;
import com.uduemc.biso.node.web.service.byfeign.impl.CategoryServiceImpl;

import cn.hutool.core.util.StrUtil;

@Service
public class SitemapServiceImpl implements SitemapService {

	@Autowired
	private HostService hostServiceImpl;

	@Autowired
	private RequestHolder requestHolder;

	@Autowired
	private SiteService siteServiceImpl;

	@Autowired
	private SiteConfigService siteConfigServiceImpl;

	@Autowired
	private PageService pageServiceImpl;

	@Autowired
	private LanguageService languageServiceImpl;

	@Autowired
	private CategoryServiceImpl categoryServiceImpl;

	@Autowired
	private SystemService systemServiceImpl;

	@Autowired
	private ArticleService articleServiceImpl;

	@Autowired
	private ProductService productServiceImpl;

	@Autowired
	private SRHeadService sRHeadServiceImpl;

	@Autowired
	private SRBodyService sRBodyServiceImpl;

	@Autowired
	private SiteUrlComponent siteUrlComponent;

	@Override
	public String xml() throws NotFound404Exception, JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		HostInfos hostInfos = hostServiceImpl.getHostInfosByHostId(requestHolder.getHostId());
		HConfig hostConfig = hostInfos.getHostConfig();
		Short isMap = hostConfig.getIsMap();

		String result = "";
		if (isMap == null || isMap.shortValue() == (short) 0) {
			throw new NotFound404Exception("未开启站点地图！");
		} else if (isMap.shortValue() == (short) 1) {
			// 系统默认站点地图
			result = StringUtils.trimWhitespace(currnetxml());
		} else if (isMap.shortValue() == (short) 2) {
			// 用户自定义的站点地图
			result = StringUtils.trimWhitespace(hostConfig.getSitemapxml());
		}
		return result;
	}

	@Override
	public String html() throws NotFound404Exception, JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		// 获取默认的站点
		Site defaultSite = siteServiceImpl.getDefaultSite(requestHolder.getHostId());
		SConfig sConfig = siteConfigServiceImpl.getInfoBySiteId(requestHolder.getHostId(), defaultSite.getId());
		SysLanguage language = languageServiceImpl.getLanguageBySite(defaultSite);

		AccessSite accessSite = new AccessSite();
		accessSite.setPreview(false);
		accessSite.setUri("/index.html");
		accessSite.setLanno("");
		accessSite.setSite(defaultSite);
		accessSite.setSiteConfig(sConfig);
		accessSite.setLanguage(language);
		// 加入 holder
		requestHolder.set(accessSite);

		// 通过 PageUtil 获取当前页面的 FeignPageUtil 数据
		FeignPageUtil feignPageUtil = new FeignPageUtil();
		feignPageUtil.setHostId(requestHolder.getHostId()).setSiteId(defaultSite.getId()).setBootPage(false).setDefaultPage(true);
		SitePage sitePage = pageServiceImpl.getSitePageByFeignPageUtil(feignPageUtil);
		AccessPage accessPage = new AccessPage();
		accessPage.setSitePage(sitePage);
		requestHolder.set(accessPage);

		SRHtml srHtml = new SRHtml();
		SRHead srHead = srHtml.getHead();
		// 制作 head 部分
		sRHeadServiceImpl.makeSitemapHtmlSRHead(srHead);
		srHead.setTitle(language.getId().longValue() == 1 ? new StringBuilder("<title>网站地图</title>") : new StringBuilder("<title>Site Map</title>"));

		SRBody srBody = srHtml.getBody();
		// 制作 body 部分
		sRBodyServiceImpl.makeSitemapHtmlSRBody(srBody);
		// 输出对象
		return SRHtmlUtil.getHtml(srHtml);
	}

	@Override
	public String currnetxml() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		StringBuffer xml = new StringBuffer();
		// 头部
		xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
		xml.append("<urlset\r\n" + "      xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"\r\n"
				+ "      xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n"
				+ "      xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9\r\n"
				+ "            http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\">");

		// 获取默认的站点
		Site defaultSite = siteServiceImpl.getDefaultSite(requestHolder.getHostId());
		List<SPage> pages = pageServiceImpl.getPages(requestHolder.getHostId(), defaultSite.getId());

		// pageXml
		StringBuffer pageXml = new StringBuffer();
		pageXml.append(getPageXml(requestHolder.getRequest(), "", pages));
		List<Site> listSite = siteServiceImpl.getOkSiteList(requestHolder.getHostId());
		for (Site site : listSite) {
			if (site.getId().longValue() == defaultSite.getId().longValue()) {
				continue;
			}
			List<SPage> listSPage = pageServiceImpl.getPages(requestHolder.getHostId(), site.getId());
			SysLanguage languageBySite = languageServiceImpl.getLanguageBySite(site);
			pageXml.append(getPageXml(requestHolder.getRequest(), languageBySite.getLanNo(), listSPage));
		}

		// categoryXml
		StringBuffer categoryXml = new StringBuffer();
		if (!CollectionUtils.isEmpty(pages)) {
			for (SPage page : pages) {
				if (page.getSystemId() != null && page.getSystemId().longValue() > 0) {
					long systemId = page.getSystemId().longValue();
					// 获取该系统下的所有分类
					List<SCategories> listSCategories = categoryServiceImpl.getInfosByHostSiteSystemIdAndDefaultOrder(requestHolder.getHostId(),
							defaultSite.getId(), systemId);
					categoryXml.append(getCategoryXml(requestHolder.getRequest(), "", page, listSCategories));
				}
			}
		}
		for (Site site : listSite) {
			if (site.getId().longValue() == defaultSite.getId().longValue()) {
				continue;
			}
			List<SPage> listSPage = pageServiceImpl.getPages(requestHolder.getHostId(), site.getId());
			if (!CollectionUtils.isEmpty(listSPage)) {
				for (SPage page : listSPage) {
					if (page.getSystemId() != null && page.getSystemId().longValue() > 0) {
						long systemId = page.getSystemId().longValue();
						// 获取该系统下的所有分类
						List<SCategories> listSCategories = categoryServiceImpl.getInfosByHostSiteSystemIdAndDefaultOrder(requestHolder.getHostId(),
								site.getId(), systemId);
						SysLanguage languageBySite = languageServiceImpl.getLanguageBySite(site);
						categoryXml.append(getCategoryXml(requestHolder.getRequest(), languageBySite.getLanNo(), page, listSCategories));
					}
				}
			}
		}

		// itemXml
		StringBuffer itemXml = new StringBuffer();
		if (!CollectionUtils.isEmpty(pages)) {
			for (SPage page : pages) {
				if (page.getSystemId() != null && page.getSystemId().longValue() > 0) {
					long systemId = page.getSystemId().longValue();
					// 获取系统数据
					SSystem system = systemServiceImpl.findInfo(requestHolder.getHostId(), defaultSite.getId(), systemId);
					itemXml.append(getItemXml(requestHolder.getRequest(), "", page, system));
				}
			}
		}
		for (Site site : listSite) {
			if (site.getId().longValue() == defaultSite.getId().longValue()) {
				continue;
			}
			List<SPage> listSPage = pageServiceImpl.getPages(requestHolder.getHostId(), site.getId());
			if (!CollectionUtils.isEmpty(listSPage)) {
				for (SPage page : listSPage) {
					if (page.getSystemId() != null && page.getSystemId().longValue() > 0) {
						long systemId = page.getSystemId().longValue();
						SSystem system = systemServiceImpl.findInfo(requestHolder.getHostId(), site.getId(), systemId);
						SysLanguage languageBySite = languageServiceImpl.getLanguageBySite(site);
						itemXml.append(getItemXml(requestHolder.getRequest(), languageBySite.getLanNo(), page, system));
					}
				}
			}
		}

		// 写入页面
		xml.append(pageXml);
		// 写入页面分类
		xml.append(categoryXml);
		// 写入详情内容页面
		xml.append(itemXml);
		// 中间主体
		xml.append("");
		// 尾部
		xml.append("</urlset>");
		return xml.toString();
	}

	protected StringBuffer getItemXml(HttpServletRequest request, String langno, SPage page, SSystem system)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		StringBuffer result = new StringBuffer();
		if (system == null) {
			return result;
		}
		Long hostId = page.getHostId();
		Long siteId = page.getSiteId();
		Long systemId = system.getId();
		// 进入系统内容获取
		long systemTypeId = system.getSystemTypeId();
		if (systemTypeId == 1) {
			// 带分类文章系统
			PageInfo<Article> pageInfoArticle = articleServiceImpl.getInfosBySystemCategoryIdKeywordAndPage(hostId, siteId, systemId, -1, "", 1, 1000);
			if (pageInfoArticle != null && pageInfoArticle.getTotal() > 0) {
				List<Article> listArticle = pageInfoArticle.getList();
				result.append(getArticleXml(request, langno, page, listArticle));
			}
		} else if (systemTypeId == 2) {
			// 不带分类文章系统
			PageInfo<Article> pageInfoArticle = articleServiceImpl.getInfosBySystemCategoryIdKeywordAndPage(hostId, siteId, systemId, -1, "", 1, 1000);
			if (pageInfoArticle != null && pageInfoArticle.getTotal() > 0) {
				List<Article> listArticle = pageInfoArticle.getList();
				result.append(getArticleXml(request, langno, page, listArticle));
			}
		} else if (systemTypeId == 3) {
			// 带分类产品系统
			PageInfo<ProductDataTableForList> pageInfoProductDataTableForList = productServiceImpl.getInfosBySystemCategoryIdKeywordAndPage(hostId, siteId,
					systemId, -1, "", 1, 1000);
			if (pageInfoProductDataTableForList != null && pageInfoProductDataTableForList.getTotal() > 0) {
				List<ProductDataTableForList> listProductDataTableForList = pageInfoProductDataTableForList.getList();
				result.append(getProductXml(request, langno, page, listProductDataTableForList));
			}
		} else if (systemTypeId == 4) {
			// 不带分类产品系统
			PageInfo<ProductDataTableForList> pageInfoProductDataTableForList = productServiceImpl.getInfosBySystemCategoryIdKeywordAndPage(hostId, siteId,
					systemId, -1, "", 1, 1000);
			if (pageInfoProductDataTableForList != null && pageInfoProductDataTableForList.getTotal() > 0) {
				List<ProductDataTableForList> listProductDataTableForList = pageInfoProductDataTableForList.getList();
				result.append(getProductXml(request, langno, page, listProductDataTableForList));
			}
		}
		return result;
	}

	protected StringBuffer getProductXml(HttpServletRequest request, String langno, SPage page, List<ProductDataTableForList> listProductDataTableForList) {
		StringBuffer result = new StringBuffer();
		if (CollectionUtils.isEmpty(listProductDataTableForList)) {
			return result;
		}
		String lastmod = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDate.now());
		for (ProductDataTableForList productDataTableForList : listProductDataTableForList) {
			String loc = getProducttUrl(request, langno, page, productDataTableForList);
			result.append("<url>");
			result.append("<loc>" + loc + "</loc>");
			result.append("<priority>0.5</priority>");
			result.append("<lastmod>" + lastmod + "</lastmod>");
			result.append("<changefreq>weekly</changefreq>");
			result.append("</url>");
		}
		return result;
	}

	protected String getProducttUrl(HttpServletRequest request, String langno, SPage sPage, ProductDataTableForList productDataTableForList) {
		String serverName = request.getServerName();
		int port = request.getServerPort();
		String scheme = request.getScheme();

		SProduct sproduct = productDataTableForList.getSproduct();

		SSystemItemCustomLink sSystemItemCustomLink = null;
		try {
			sSystemItemCustomLink = systemServiceImpl.findOkOneByHostSiteSystemItemId(sproduct.getHostId(), sproduct.getSiteId(), sproduct.getSystemId(),
					sproduct.getId());
		} catch (IOException e) {
		}

		String productHref = siteUrlComponent.getProductHref(sPage, sproduct, sSystemItemCustomLink);
		
		String prefixHref = siteUrlComponent.prefixHref();
		productHref = StrUtil.replace(productHref, prefixHref, "");

		return scheme + "://" + serverName + (port == 80 || port == 443 ? "" : ":" + port)+ (StringUtils.isEmpty(langno) ? "" : "/" + langno) + productHref;
	}

	protected StringBuffer getArticleXml(HttpServletRequest request, String langno, SPage page, List<Article> listArticle) {
		StringBuffer result = new StringBuffer();
		if (CollectionUtils.isEmpty(listArticle)) {
			return result;
		}
		String lastmod = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDate.now());
		for (Article article : listArticle) {
			String loc = getArticletUrl(request, langno, page, article);
			result.append("<url>");
			result.append("<loc>" + loc + "</loc>");
			result.append("<priority>0.5</priority>");
			result.append("<lastmod>" + lastmod + "</lastmod>");
			result.append("<changefreq>weekly</changefreq>");
			result.append("</url>");
		}
		return result;
	}

	protected String getArticletUrl(HttpServletRequest request, String langno, SPage sPage, Article article) {
		String serverName = request.getServerName();
		int port = request.getServerPort();
		String scheme = request.getScheme();

		SSystemItemCustomLink sSystemItemCustomLink = null;
		try {
			sSystemItemCustomLink = systemServiceImpl.findOkOneByHostSiteSystemItemId(article.getSArticle().getHostId(), article.getSArticle().getSiteId(),
					article.getSArticle().getSystemId(), article.getSArticle().getId());
		} catch (IOException e) {
		}

		String articleHref = siteUrlComponent.getArticleHref(sPage, article.getSArticle(), sSystemItemCustomLink);
		
		String prefixHref = siteUrlComponent.prefixHref();
		articleHref = StrUtil.replace(articleHref, prefixHref, "");

		return scheme + "://" + serverName + (port == 80 || port == 443 ? "" : ":" + port) + (StringUtils.isEmpty(langno) ? "" : "/" + langno)
				+ articleHref;
	}

	protected static StringBuffer getCategoryXml(HttpServletRequest request, String langno, SPage page, List<SCategories> listSCategories) {
		StringBuffer result = new StringBuffer();
		if (CollectionUtils.isEmpty(listSCategories)) {
			return result;
		}
		String lastmod = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDate.now());
		for (SCategories category : listSCategories) {
			String loc = getCategorytUrl(request, langno, page, category);
			result.append("<url>");
			result.append("<loc>" + loc + "</loc>");
			result.append("<priority>0.8</priority>");
			result.append("<lastmod>" + lastmod + "</lastmod>");
			result.append("<changefreq>weekly</changefreq>");
			result.append("</url>");
		}
		return result;
	}

	protected static String getCategorytUrl(HttpServletRequest request, String langno, SPage sPage, SCategories category) {
		String serverName = request.getServerName();
		int port = request.getServerPort();
		String scheme = request.getScheme();
		return scheme + "://" + serverName + (port == 80 || port == 443 ? "" : ":" + port) + getUri(langno, sPage, category);
	}

	protected static StringBuffer getPageXml(HttpServletRequest request, String langno, List<SPage> pages) {
		StringBuffer pagesXml = new StringBuffer();
		if (CollectionUtils.isEmpty(pages)) {
			return pagesXml;
		}
		String lastmod = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDate.now());
		for (SPage page : pages) {
			String loc = getPagetUrl(request, langno, page);
			pagesXml.append("<url>");
			pagesXml.append("<loc>" + loc + "</loc>");
			pagesXml.append("<priority>1.0</priority>");
			pagesXml.append("<lastmod>" + lastmod + "</lastmod>");
			pagesXml.append("<changefreq>weekly</changefreq>");
			pagesXml.append("</url>");
		}
		return pagesXml;
	}

	protected static String getPagetUrl(HttpServletRequest request, String langno, SPage sPage) {
		String serverName = request.getServerName();
		int port = request.getServerPort();
		String scheme = request.getScheme();
		return scheme + "://" + serverName + (port == 80 || port == 443 ? "" : ":" + port) + getUri(langno, sPage);
	}

//	protected static String getUri(String langno, SPage sPage, ProductDataTableForList productDataTableForList) {
//		return (StringUtils.isEmpty(langno) ? "" : "/" + langno) + SiteUrlUtil.getPath(sPage, productDataTableForList.getSproduct());
//	}

//	protected static String getUri(String langno, SPage sPage, Article article) {
//		return (StringUtils.isEmpty(langno) ? "" : "/" + langno) + SiteUrlUtil.getPath(sPage, article.getSArticle());
//	}

	protected static String getUri(String langno, SPage sPage, SCategories category) {
		return (StringUtils.isEmpty(langno) ? "" : "/" + langno) + SiteUrlUtil.getPath(sPage, category);
	}

	protected static String getUri(String langno, SPage sPage) {
		return (StringUtils.isEmpty(langno) ? "" : "/" + langno) + SiteUrlUtil.getPath(sPage);
	}

}
